package com.atguigu.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.payment.client.PaymentFeignClient;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * ClassName: OrderReceiver
 * Package: com.atguigu.gmall.order.receiver
 * Description:
 *
 * @Author 刘轩
 * @Create 2023-09-05 19:02
 * @Version 1.0
 */

@Component
@Slf4j
public class OrderReceiver {

    @Autowired
    private OrderService orderService;

    @Autowired
    private PaymentFeignClient paymentFeignClient;










    // queues:必须在消费服务中有绑定关系或绑定依赖
    // bindings:初始化绑定关系，同时监听队列
    // 按照延迟插件的方式，我们自己制作一个配置类  在配置类中设置好利用延迟插件发送消息
    // 因此，在监听的时候，就可以直接监听队列！
    @SneakyThrows
    @RabbitListener(queues = MqConst.QUEUE_ORDER_CANCEL)
    public void orderCancel(Long orderId, Message message, Channel channel){
        try {
            // 判断是否为空
            if(null != orderId){
               // 修改之前，查询到当前订单对象，根据订单状态来判断是否需要取消订单，保存消息幂等性
                OrderInfo orderInfo = orderService.getById(orderId);
                // 订单记录
                if(null != orderInfo && "UNPAID".equals(orderInfo.getOrderStatus()) &&"UNPAID".equals(orderInfo.getProcessStatus())){
                    // 判断是否电商本地交易记录 paymentInfo
                    PaymentInfo paymentInfo = paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());
                    // 判断本地交易记录
                    if(paymentInfo != null && "UNPAID".equals(paymentInfo.getPaymentStatus())){
                          // 还有可能有关闭支付宝交易记录
                        Result result = paymentFeignClient.checkPayment(orderId);
                        Boolean flag = (Boolean)result.getData();
                        if (flag){
                            // 有这个交易记录 需要关闭支付宝交易记录
                            Result resultAliPay = paymentFeignClient.closeAlipay(orderId);
                            Boolean isSuccess = (Boolean) resultAliPay.getData();
                            // 判断是否关闭成功
                            if(isSuccess){
                                // 关闭成功 -- 说明没有付款
                                orderService.execExpiredOrder(orderId,"2");
                            }else {
                                // 没有关闭成功 说明在过期的一瞬间支付成功
                            }
                        }else {
                            // 需要关闭 orderinfo paymentinfo
                            orderService.execExpiredOrder(orderId,"2");
                        }
                    }else {
                        // 只需要关闭orderinfo
                        // 执行取消订单业务
                        orderService.execExpiredOrder(orderId,"1");
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 手动签收确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    /**
     *  更新订单状态关闭订单
     * @param orderId
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_ORDER_CLOSED,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_ORDER_CLOSED),
            key = {MqConst.ROUTING_ORDER_CLOSED}
    ))
    public void closeOrder(Long orderId,Message message ,Channel channel){
        try {
            // 判断
            if(orderId != null){
                OrderInfo orderInfo = orderService.getById(orderId);
                // 利用业务字段防止消息重发消费
                if(null != orderInfo && !"CLOSED".equals(orderInfo.getOrderStatus())&&!"CLOSED".equals(orderInfo.getProcessStatus())){
                    // 根据订单id 修改订单状态
                    orderService.updateOrderStatus(orderId, ProcessStatus.CLOSED);
                    // 发送消息给库存系统，通知系统减库存
                     orderService.senMsgToWare(orderId);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
// 手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    /**
     * 监听支付成功修改订单状态
     * @param orderId
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            key = {MqConst.ROUTING_PAYMENT_PAY}
    ))
    public void paymentPay(Long orderId,Message message ,Channel channel){
        try {
            // 判断
            if(orderId != null){
                OrderInfo orderInfo = orderService.getById(orderId);
                // 利用业务字段防止消息重发消费
                if(null != orderInfo && "UNPAID".equals(orderInfo.getOrderStatus())&&"UNPAID".equals(orderInfo.getProcessStatus())){
                    // 根据订单id 修改订单状态
                    orderService.updateOrderStatus(orderId, ProcessStatus.PAID);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
// 手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
    //  监听库存系统发送的减库存结果
    //  {"orderId":1001,"status":DEDUCTED};
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            key = {MqConst.ROUTING_WARE_ORDER}
    ))
    public void wareOrder(String wareJson,Message message, Channel channel){
        try {
            //  先判断
            if (!StringUtils.isEmpty(wareJson)){
                //  将字符串转换为JavaObject
                Map map = JSON.parseObject(wareJson, Map.class);
                String orderId = (String) map.get("orderId");
                String status = (String) map.get("status");
                //  判断状态
                if ("DEDUCTED".equals(status)){
                    //  说明减库存成功.
                    this.orderService.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.WAITING_DELEVER);
                } else {
                    //  减库存失败.
                    this.orderService.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.STOCK_EXCEPTION);
                    log.info("出库失败{}",orderId);
                    //  通知库存管理员要求补货...  需要从其他仓库进行补货。如果发货成功了; 然后再将这个减库存消息重发一次。 手动更新当前减库存状态.
                    //  如果没有补货成功，则人工客服介入; 亲，不好啥意思的，我等. 不行！给钱！ 调用退款接口：
                }
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        //  手动签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
